/**
 * EduVerse Credentials - 钱包应用模块
 * 
 * 实现持有者钱包应用的核心功能，包括DID管理、凭证管理、ZKP生成和VP创建等。
 * 注意：这是一个简化的后端API实现，实际项目中可能需要前端UI组件。
 */

const express = require('express');
const { initPolygonIdSDK } = require('../utils/sdk-init');
const { initMockSDK } = require('../utils/sdk-mock');
const { 
  createPolygonIdIdentity, 
  createEthrIdentity 
} = require('../core/did');
const { 
  addDataIntegrityProof, 
  createVerifiablePresentation,
  embedZKPInPresentation 
} = require('../core/vc');
const { 
  generateZKProof 
} = require('../core/zkp');
const { v4: uuidv4 } = require('uuid');
const fs = require('fs');
const path = require('path');

// 数据文件路径
const WALLET_DATA_DIR = path.join(__dirname, '..', '..', 'data', 'wallet');
const DIDS_FILE = path.join(WALLET_DATA_DIR, 'dids.json');
const CREDENTIALS_FILE = path.join(WALLET_DATA_DIR, 'credentials.json');

// 确保数据目录存在
if (!fs.existsSync(WALLET_DATA_DIR)) {
  fs.mkdirSync(WALLET_DATA_DIR, { recursive: true });
}

/**
 * 从JSON文件加载数据
 * @param {string} filePath 文件路径
 * @returns {Map} 加载的数据，如果文件不存在或为空则返回新的Map
 */
function loadDataFromFile(filePath) {
  try {
    if (fs.existsSync(filePath)) {
      const fileData = fs.readFileSync(filePath, 'utf-8');
      if (fileData) {
        const parsedData = JSON.parse(fileData);
        // 从对象数组转换回Map
        if (Array.isArray(parsedData)) {
          return new Map(parsedData);
        }
        // 兼容旧的直接存储Map为Object的格式（不推荐）
        return new Map(Object.entries(parsedData)); 
      }
    }
  } catch (error) {
    console.error(`从 ${filePath} 加载数据失败:`, error);
  }
  return new Map();
}

/**
 * 将数据保存到JSON文件
 * @param {string} filePath 文件路径
 * @param {Map} data 要保存的Map数据
 */
function saveDataToFile(filePath, data) {
  try {
    // 将Map转换为对象数组以便序列化
    const dataArray = Array.from(data.entries());
    fs.writeFileSync(filePath, JSON.stringify(dataArray, null, 2), 'utf-8');
  } catch (error) {
    console.error(`保存数据到 ${filePath} 失败:`, error);
  }
}

class WalletApp {
  constructor() {
    this.app = express();
    this.router = express.Router();
    this.sdkComponents = null;
    
    // 从文件加载数据或初始化为空的Map
    this.walletStorage = {
      dids: loadDataFromFile(DIDS_FILE),
      credentials: loadDataFromFile(CREDENTIALS_FILE)
    };
    
    this.setupRoutes();
  }
  
  /**
   * 初始化Polygon ID SDK和路由
   */
  async initialize(config = {}) {
    try {
      console.log("Initializing wallet app...");
      
      try {
        // 尝试初始化真实SDK
        this.sdkComponents = await initPolygonIdSDK(config);
      } catch (sdkError) {
        // 如果真实SDK初始化失败，使用模拟SDK
        console.warn("使用模拟SDK进行开发...", sdkError.message);
        this.sdkComponents = await initMockSDK(config);
        this._usingMockSdk = true;
      }
      
      this.app.use(express.json());
      
      // 两种路径都注册路由，确保兼容性
      this.app.use('/api/wallet', this.router);  // 前端直接使用的路径：/api/wallet/xxx
      this.app.use('/api', this.router);         // 通过代理转发的路径：/wallet/api/xxx
      
      // API版本和文档端点
      this.router.get('/version', (req, res) => {
        res.json({
          app: 'EduVerse Credentials - Wallet',
          version: '0.1.0',
          apiVersion: 'v1'
        });
      });

      // 健康检查端点
      this.router.get('/health', (req, res) => {
        res.json({ 
          status: 'ok', 
          timestamp: new Date().toISOString(),
          usingMockSdk: this._usingMockSdk 
        });
      });
      
      // 路由调试端点
      this.router.get('/routes', (req, res) => {
        const routes = [];
        this.router.stack.forEach(layer => {
          if (layer.route) {
            const path = layer.route.path;
            const methods = Object.keys(layer.route.methods).map(m => m.toUpperCase());
            routes.push({ path, methods });
          }
        });
        res.json({ routes });
      });
      
      console.log("Wallet app initialized", this._usingMockSdk ? "(使用模拟SDK)" : "");
      return this;
    } catch (error) {
      console.error("Error initializing wallet app:", error);
      throw error;
    }
  }
  
  /**
   * 设置API路由
   */
  setupRoutes() {
    // DID管理相关路由
    this.router.post('/dids/create-polygonid', this.createPolygonIdIdentity.bind(this));
    this.router.post('/dids/create-ethr', this.createEthrIdentity.bind(this));
    this.router.get('/dids', this.listDIDs.bind(this));
    
    // 加载示例数据路由
    this.router.post('/dids/load-samples', this.loadSampleDids.bind(this));
    
    // 凭证管理相关路由
    this.router.post('/credentials', this.receiveCredential.bind(this));
    this.router.get('/credentials', this.listCredentials.bind(this));
    
    // 凭证导入相关路由 - 需要放在具体ID路由之前
    this.router.get('/credentials/import', this.importCredential.bind(this));
    this.router.post('/credentials/import', this.importCredential.bind(this));

    // 加载示例数据路由
    this.router.post('/credentials/load-samples', this.loadSampleCredentials.bind(this));
    
    // 凭证详情路由
    this.router.get('/credentials/:id', this.getCredentialDetails.bind(this));
    this.router.delete('/credentials/:id', this.deleteCredential.bind(this));
    
    // ZKP相关路由
    this.router.post('/proofs/generate', this.generateProof.bind(this));
    
    // VP相关路由
    this.router.post('/presentations/create', this.createPresentation.bind(this));
  }
  
  /**
   * 启动服务
   */
  start(port = process.env.PORT || 3000) {
    return new Promise((resolve) => {
      const server = this.app.listen(port, () => {
        console.log(`Wallet app listening on port ${port}`);
        resolve(server);
      });
    });
  }
  
  /**
   * 创建did:polygonid身份
   */
  async createPolygonIdIdentity(req, res) {
    try {
      const { identityWallet } = this.sdkComponents;
      
      const { did, authCredential } = await createPolygonIdIdentity(identityWallet);
      
      const didInfo = {
        id: did.string(),
        method: 'polygonid',
        created: new Date().toISOString(),
        authCredential
      };
      
      this.walletStorage.dids.set(didInfo.id, didInfo);
      saveDataToFile(DIDS_FILE, this.walletStorage.dids); // 保存到文件
      
      res.status(201).json({
        success: true,
        did: didInfo
      });
    } catch (error) {
      console.error("Error creating did:polygonid identity:", error);
      res.status(500).json({
        success: false,
        error: error.message
      });
    }
  }
  
  /**
   * 创建did:ethr身份
   */
  async createEthrIdentity(req, res) {
    try {
      const { network } = req.body || {};
      
      const didInfo = await createEthrIdentity(network || 'amoy');
      
      const didRecord = {
        id: didInfo.did,
        method: 'ethr',
        created: new Date().toISOString(),
        address: didInfo.address,
        privateKey: didInfo.privateKey
      };
      
      this.walletStorage.dids.set(didRecord.id, didRecord);
      saveDataToFile(DIDS_FILE, this.walletStorage.dids); // 保存到文件
      
      res.status(201).json({
        success: true,
        did: {
          ...didRecord,
          privateKey: undefined // 不返回私钥
        }
      });
    } catch (error) {
      console.error("Error creating did:ethr identity:", error);
      res.status(500).json({
        success: false,
        error: error.message
      });
    }
  }
  
  /**
   * 列出所有DID
   */
  listDIDs(req, res) {
    try {
      const dids = Array.from(this.walletStorage.dids.values()).map(did => ({
        ...did,
        privateKey: undefined, // 不返回私钥
        authCredential: undefined // 不返回认证凭证
      }));
      
      res.status(200).json({
        success: true,
        dids
      });
    } catch (error) {
      console.error("Error listing DIDs:", error);
      res.status(500).json({
        success: false,
        error: error.message
      });
    }
  }
  
  /**
   * 接收凭证
   */
  async receiveCredential(req, res) {
    try {
      const { credential } = req.body;
      
      if (!credential) {
        return res.status(400).json({
          success: false,
          error: "Credential is required"
        });
      }
      
      const { credentialWallet } = this.sdkComponents;
      await credentialWallet.save(credential); // SDK自身的保存逻辑（可能也是内存或需要配置）
      
      const credentialId = credential.id || `credential-${uuidv4()}`;
      const storedCredential = {
        id: credentialId,
        type: credential.type,
        issuer: credential.issuer,
        issuanceDate: credential.issuanceDate,
        expirationDate: credential.expirationDate,
        credential // 存储完整的凭证对象
      };

      this.walletStorage.credentials.set(credentialId, storedCredential);
      saveDataToFile(CREDENTIALS_FILE, this.walletStorage.credentials); // 保存到文件
      
      res.status(201).json({
        success: true,
        credentialId
      });
    } catch (error) {
      console.error("Error receiving credential:", error);
      res.status(500).json({
        success: false,
        error: error.message
      });
    }
  }
  
  /**
   * 列出所有凭证
   */
  listCredentials(req, res) {
    try {
      const credentials = Array.from(this.walletStorage.credentials.values()).map(cred => ({
        id: cred.id,
        type: cred.type,
        issuer: cred.issuer,
        issuanceDate: cred.issuanceDate,
        expirationDate: cred.expirationDate,
        revoked: cred.revoked || false // 确保返回revoked状态
      }));
      
      res.status(200).json({
        success: true,
        credentials
      });
    } catch (error) {
      console.error("Error listing credentials:", error);
      res.status(500).json({
        success: false,
        error: error.message
      });
    }
  }
  
  /**
   * 获取凭证详情
   */
  getCredentialDetails(req, res) {
    try {
      const { id } = req.params;
      
      const credential = this.walletStorage.credentials.get(id);
      
      if (!credential) {
        return res.status(404).json({
          success: false,
          error: "Credential not found"
        });
      }
      
      // 添加过期状态和撤销状态检查
      const now = new Date();
      const isExpired = credential.expirationDate && new Date(credential.expirationDate) < now;
      const isRevoked = credential.revoked || false;
      
      res.status(200).json({
        success: true,
        credential: {
          ...credential,
          status: {
            isExpired,
            isRevoked,
            isValid: !isExpired && !isRevoked
          }
        }
      });
    } catch (error) {
      console.error("Error getting credential details:", error);
      res.status(500).json({
        success: false,
        error: error.message
      });
    }
  }
  
  /**
   * 删除凭证(逻辑删除)
   */
  deleteCredential(req, res) {
    try {
      const { id } = req.params;
      
      if (!this.walletStorage.credentials.has(id)) {
        return res.status(404).json({
          success: false,
          error: "Credential not found"
        });
      }
      
      this.walletStorage.credentials.delete(id);
      saveDataToFile(CREDENTIALS_FILE, this.walletStorage.credentials); // 保存到文件
      
      res.status(200).json({
        success: true,
        message: `Credential ${id} deleted`
      });
    } catch (error) {
      console.error("Error deleting credential:", error);
      res.status(500).json({
        success: false,
        error: error.message
      });
    }
  }
  
  /**
   * 导入凭证
   */
  importCredential(req, res) {
    try {
      // 检查请求方法
      if (req.method === 'GET') {
        // 返回导入页面相关数据
        return res.status(200).json({
          success: true,
          importOptions: {
            supportedFormats: ['W3C VC', 'JSON-LD', 'JWT']
          }
        });
      } else if (req.method === 'POST') {
        // 处理凭证导入
        const { credential, format } = req.body || {};
        
        if (!credential) {
          return res.status(400).json({
            success: false,
            error: "Credential data is required"
          });
        }
        
        // 简单验证凭证格式
        if (!credential.id && !credential['@id']) {
          return res.status(400).json({
            success: false,
            error: "Invalid credential format: missing id"
          });
        }
        
        // 保存导入的凭证
        const credentialId = credential.id || credential['@id'] || `imported-${uuidv4()}`;
        const importedCredentialData = {
          id: credentialId,
          type: Array.isArray(credential.type) ? credential.type.join(',') : credential.type,
          issuer: credential.issuer,
          issuanceDate: credential.issuanceDate || new Date().toISOString(),
          imported: true,
          importedAt: new Date().toISOString(),
          credential // 存储完整的导入凭证对象
        };

        this.walletStorage.credentials.set(credentialId, importedCredentialData);
        saveDataToFile(CREDENTIALS_FILE, this.walletStorage.credentials); // 保存到文件
        
        return res.status(201).json({
          success: true,
          message: "Credential imported successfully",
          credentialId
        });
      } else {
        return res.status(405).json({
          success: false,
          error: "Method not allowed"
        });
      }
    } catch (error) {
      console.error("Error importing credential:", error);
      res.status(500).json({
        success: false,
        error: error.message
      });
    }
  }
  
  /**
   * 生成ZK证明
   */
  async generateProof(req, res) {
    try {
      const { proofRequest, holderDid, credentialId } = req.body;
      
      if (!proofRequest || !holderDid || !credentialId) {
        return res.status(400).json({
          success: false,
          error: "proofRequest, holderDid and credentialId are required"
        });
      }
      
      // 获取持有者DID对象
      const didInfo = this.walletStorage.dids.get(holderDid);
      if (!didInfo) {
        return res.status(404).json({
          success: false,
          error: "Holder DID not found"
        });
      }
      
      // 获取凭证
      const credentialInfo = this.walletStorage.credentials.get(credentialId);
      if (!credentialInfo) {
        return res.status(404).json({
          success: false,
          error: "Credential not found"
        });
      }
      
      // 生成ZKP
      const { proofService } = this.sdkComponents;
      
      const holderDID = didInfo; // 简化: 在实际实现中，可能需要转换为适当的对象格式
      const credential = credentialInfo.credential;
      
      const zkResponse = await generateZKProof(proofService, proofRequest, holderDID, credential);
      
      res.status(200).json({
        success: true,
        proof: zkResponse.proof,
        circuitId: proofRequest.circuitId
      });
    } catch (error) {
      console.error("Error generating proof:", error);
      res.status(500).json({
        success: false,
        error: error.message
      });
    }
  }
  
  /**
   * 创建可验证演示(VP)
   */
  async createPresentation(req, res) {
    try {
      const { 
        credentialIds, 
        holderDid, 
        challenge,
        domain,
        zkProof,
        circuitId,
        includeCredentials = true // 修改为默认包含凭证
      } = req.body;
      
      if (!holderDid || (!credentialIds && !zkProof)) {
        return res.status(400).json({
          success: false,
          error: "holderDid and either credentialIds or zkProof are required"
        });
      }
      
      // 获取持有者DID信息
      const didInfo = this.walletStorage.dids.get(holderDid);
      if (!didInfo) {
        return res.status(404).json({
          success: false,
          error: "Holder DID not found"
        });
      }
      
      // 创建一个基本的VP，以使功能正常响应
      let credentials = [];
      
      if (credentialIds && credentialIds.length > 0) {
        // 使用凭证创建VP
        credentials = credentialIds.map(id => {
          const credInfo = this.walletStorage.credentials.get(id);
          if (!credInfo) {
            console.warn(`Credential ${id} not found`);
            return null;
          }
          return credInfo.credential;
        }).filter(Boolean);
      }
      
      // 创建简单的VP
      const presentation = {
        "@context": ["https://www.w3.org/ns/credentials/v2"],
        "id": `urn:uuid:${require('uuid').v4()}`,
        "type": ["VerifiablePresentation"],
        "holder": holderDid,
        "verifiableCredential": credentials,
        "proof": {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": new Date().toISOString(),
          "proofPurpose": "authentication",
          "verificationMethod": `${holderDid}#keys-1`,
          "challenge": challenge || "mock-challenge",
          "domain": domain || "example.com",
          "proofValue": "mockSignatureValue"
        }
      };
      
      // 如果提供了ZKP，则嵌入到VP中
      if (zkProof && circuitId) {
        presentation.proof.zkp = {
          circuitId,
          proofData: zkProof
        };
      }
      
      res.status(200).json({
        success: true,
        presentation
      });
    } catch (error) {
      console.error("Error creating presentation:", error);
      res.status(500).json({
        success: false,
        error: "Could not create presentation with provided parameters"
      });
    }
  }

  /**
   * 加载示例凭证数据
   */
  async loadSampleCredentials(req, res) {
    try {
      console.log("加载钱包示例凭证数据...");
      
      // 加载示例凭证
      const sampleCredentialsPath = path.join(__dirname, '..', '..', '..', 'data', 'sample-credentials.json');
      let sampleCredentials = [];
      
      if (fs.existsSync(sampleCredentialsPath)) {
        console.log(`找到示例凭证文件: ${sampleCredentialsPath}`);
        sampleCredentials = JSON.parse(fs.readFileSync(sampleCredentialsPath, 'utf-8'));
      } else {
        console.log(`示例凭证文件不存在: ${sampleCredentialsPath}`);
        return res.status(404).json({
          success: false,
          error: "示例凭证文件不存在"
        });
      }
      
      // 为每个示例创建凭证
      const results = [];
      for (const sample of sampleCredentials) {
        try {
          // 为示例数据添加基本凭证字段
          const credential = {
            id: `urn:uuid:${uuidv4()}`,
            type: ["VerifiableCredential", sample.type],
            issuer: sample.data.credentialSubject.institution?.id || 
                   sample.data.credentialSubject.issuer?.id || 
                   sample.data.credentialSubject.verifier?.id || 
                   "did:example:issuer",
            issuanceDate: new Date().toISOString(),
            expirationDate: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString(), // 一年后过期
            credentialSubject: sample.data.credentialSubject
          };
          
          // 保存导入的凭证
          const credentialId = credential.id;
          const importedCredentialData = {
            id: credentialId,
            type: credential.type, // 直接保存数组，不转换为字符串
            issuer: credential.issuer,
            issuanceDate: credential.issuanceDate,
            expirationDate: credential.expirationDate,
            imported: true,
            importedAt: new Date().toISOString(),
            credential // 存储完整的导入凭证对象
          };

          this.walletStorage.credentials.set(credentialId, importedCredentialData);
          
          results.push({
            credentialId,
            type: sample.type,
            description: sample.description
          });
        } catch (sampleError) {
          console.error(`处理示例 ${sample.type} 时出错:`, sampleError);
        }
      }
      
      // 保存更新后的凭证存储
      saveDataToFile(CREDENTIALS_FILE, this.walletStorage.credentials);
      
      res.status(200).json({
        success: true,
        message: `成功加载 ${results.length} 个示例凭证`,
        credentials: results
      });
    } catch (error) {
      console.error("加载示例凭证失败:", error);
      res.status(500).json({
        success: false,
        error: `加载示例凭证失败: ${error.message}`
      });
    }
  }

  /**
   * 加载示例DID数据
   */
  async loadSampleDids(req, res) {
    try {
      console.log("加载示例DID数据...");
      
      // 加载示例DID
      const sampleDidsPath = path.join(__dirname, '..', '..', '..', 'data', 'sample-dids.json');
      let sampleDids = null;
      
      if (fs.existsSync(sampleDidsPath)) {
        console.log(`找到示例DID文件: ${sampleDidsPath}`);
        sampleDids = JSON.parse(fs.readFileSync(sampleDidsPath, 'utf-8'));
      } else {
        console.log(`示例DID文件不存在: ${sampleDidsPath}`);
        return res.status(404).json({
          success: false,
          error: "示例DID文件不存在"
        });
      }
      
      // 导入用户DID
      const results = [];
      if (sampleDids.users && Array.isArray(sampleDids.users)) {
        for (const user of sampleDids.users) {
          try {
            // 检查DID是否已存在
            if (this.walletStorage.dids.has(user.did)) {
              console.log(`DID已存在，跳过: ${user.did}`);
              continue;
            }
            
            // 添加DID到存储
            const didInfo = {
              id: user.did,
              method: user.did.split(':')[1] || 'polygonid',
              created: new Date().toISOString(),
              name: user.name,
              description: user.description,
              imported: true
            };
            
            this.walletStorage.dids.set(user.did, didInfo);
            
            results.push({
              did: user.did,
              name: user.name
            });
          } catch (error) {
            console.error(`处理示例DID ${user.did} 时出错:`, error);
          }
        }
      }
      
      // 保存更新后的DID存储
      saveDataToFile(DIDS_FILE, this.walletStorage.dids);
      
      res.status(200).json({
        success: true,
        message: `成功加载 ${results.length} 个示例DID`,
        dids: results
      });
    } catch (error) {
      console.error("加载示例DID失败:", error);
      res.status(500).json({
        success: false,
        error: `加载示例DID失败: ${error.message}`
      });
    }
  }
}

module.exports = WalletApp; 